package com.sy.utils;

import com.sy.exception.BusinessException;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Tuple;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Redis操作相关的工具类
 */
@Component
public class RedisOperations {
    @Autowired
    private JedisPool jedisPool;
    private static final String REDIS_OK_STR = "OK";

    @FunctionalInterface
    interface RedisCallBack<T> {
        T execute(Jedis jedis);
    }

    /**
     * 执行Redis命令的一个模板方法，该该方法的参数RedisCallBack是一个接口，在调用这个方法
     * 的时候只需要将RedisCallBack对应的具体实现类作为参数传入即可赋予这个方法真正的行为
     * 因为Jedis操作的步骤基本一致，所以将步骤抽象出来，将具体的行为作为参数传入
     * @param redisCallBack 这个参数对应的是一个接口数据类型
     * @param <T>
     * @return
     */
    private <T> T execute(RedisCallBack<T> redisCallBack) {
        try (Jedis jedis = jedisPool.getResource()) {
            return redisCallBack.execute(jedis);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("服务端异常...");
        }
    }

    public boolean set(String key, String value) {
        return execute(jedis -> StringUtils.equals(jedis.set(key, value), REDIS_OK_STR));
    }

    public String get(String key) {
        return execute(jedis -> jedis.get(key));
    }

    public boolean expire(String key, int seconds) {
        return execute(jedis -> jedis.expire(key, seconds) > 0);
    }

    public boolean hset(String key, String field, String value) {
        return execute(jedis -> jedis.hset(key, field, value) > 0);
    }

    public boolean hmset(String key, Map<String, String> pairs) {
        //hmset中属性对应的值不能为空
        return execute(jedis -> StringUtils.equals(jedis.hmset(key, pairs), REDIS_OK_STR));
    }

    public long hincrby(String key, String field, long value) {
        return execute(jedis -> jedis.hincrBy(key, field, value));
    }

    public Map<String, String> hgetall(String key) {
        return execute(jedis -> jedis.hgetAll(key));
    }

    public Set<String> hkeys(String key) {
        return execute(jedis -> jedis.hkeys(key));
    }

    public long hdel(String key, String... fields) {
        return execute(jedis -> jedis.hdel(key, fields));
    }

    public boolean exists(String key) {
        return execute(jedis -> jedis.exists(key));
    }

    public boolean del(String... keys) {
        return execute(jedis -> jedis.del(keys) > 0);
    }

    public boolean zadd(String key, Map<String, Double> map) {
        return execute(jedis -> jedis.zadd(key, map) > 0);
    }

    public Double zincrby(String key, String member, double score) {
        return execute(jedis -> jedis.zincrby(key, score, member));
    }

    public Set<String> zrevrange(String key, long start, long stop) {
        return execute(jedis -> jedis.zrevrange(key, start, stop));
    }

    public Long zcard(String key) {
        return execute(jedis -> jedis.zcard(key));
    }

    public Set<Tuple> zrangeWithScores(String key, long start, long end) {
        return execute(jedis -> jedis.zrangeWithScores(key, start, end));
    }

    public boolean lpush(String key, String... values) {
        return execute(jedis -> jedis.lpush(key, values) > 0);
    }

    public long lrem(String key, long count, String value) {
        return execute(jedis -> jedis.lrem(key, count, value));
    }

    public boolean ltrim(String key, long start, long end) {
        return execute(jedis -> !StringUtils.equals(jedis.ltrim(key, start, end), REDIS_OK_STR));
    }

    public long llen(String key) {
        return execute(jedis -> jedis.llen(key));
    }

    public List<String> lrange(String key, long start, long end) {
        return execute(jedis -> jedis.lrange(key, start, end));
    }

    public long incr(String key) {
        return execute(jedis -> jedis.incr(key));
    }


}
